Index: sys/netinet/ip_input.c
===================================================================
RCS file: /mnt/ncvs/src/sys/netinet/ip_input.c,v
retrieving revision 1.111.2.9
retrieving revision 1.111.2.10
diff -u -r1.111.2.9 -r1.111.2.10
--- sys/netinet/ip_input.c	2000/06/13 07:12:34	1.111.2.9
+++ sys/netinet/ip_input.c	2001/08/06 09:20:57	1.111.2.10
@@ -175,6 +175,12 @@
 #endif
 
 
+static int	ip_nfragpackets = 0;
+static int	ip_maxfragpackets;	/* initialized in ip_init() */
+SYSCTL_INT(_net_inet_ip, OID_AUTO, maxfragpackets, CTLFLAG_RW,
+	&ip_maxfragpackets, 0,
+	"Maximum number of IPv4 fragment reassembly queue entries");
+
 /*
  * We need to save the IP options in case a protocol wants to respond
  * to an incoming packet over the same route if the packet got here
@@ -235,7 +241,8 @@
 	for (i = 0; i < IPREASS_NHASH; i++)
 	    ipq[i].next = ipq[i].prev = &ipq[i];
 
-	maxnipq = nmbclusters/4;
+	maxnipq = nmbclusters / 4;
+	ip_maxfragpackets = nmbclusters / 4;
 
 	ip_id = time_second & 0xffff;
 	ipintrq.ifq_maxlen = ipqmaxlen;
@@ -766,6 +773,15 @@
 	 * If first fragment to arrive, create a reassembly queue.
 	 */
 	if (fp == 0) {
+		/*
+		 * Enforce upper bound on number of fragmented packets
+		 * for which we attempt reassembly;
+		 * If maxfrag is 0, never accept fragments.
+		 * If maxfrag is -1, accept all fragments without limitation.
+		 */
+		if ((ip_maxfragpackets >= 0) && (ip_nfragpackets >= ip_maxfragpackets))
+			goto dropfrag;
+		ip_nfragpackets++;
 		if ((t = m_get(M_DONTWAIT, MT_FTABLE)) == NULL)
 			goto dropfrag;
 		fp = mtod(t, struct ipq *);
@@ -908,6 +924,7 @@
 	remque(fp);
 	nipq--;
 	(void) m_free(dtom(fp));
+	ip_nfragpackets--;
 	m->m_len += (IP_VHL_HL(ip->ip_vhl) << 2);
 	m->m_data -= (IP_VHL_HL(ip->ip_vhl) << 2);
 	/* some debugging cruft by sklower, below, will go away soon */
@@ -948,6 +965,7 @@
 	}
 	remque(fp);
 	(void) m_free(dtom(fp));
+	ip_nfragpackets--;
 	nipq--;
 }
 
@@ -973,6 +991,20 @@
 			if (fp->prev->ipq_ttl == 0) {
 				ipstat.ips_fragtimeout++;
 				ip_freef(fp->prev);
+			}
+		}
+	}
+	/*
+	 * If we are over the maximum number of fragments
+	 * (due to the limit being lowered), drain off
+	 * enough to get down to the new limit.
+	 */
+	for (i = 0; i < IPREASS_NHASH; i++) {
+		if (ip_maxfragpackets >= 0) {
+			while ((ip_nfragpackets > ip_maxfragpackets) &&
+				(ipq[i].next != &ipq[i])) {
+				ipstat.ips_fragdropped++;
+				ip_freef(ipq[i].next);
 			}
 		}
 	}
